using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using UnityEngine;
using UnityEngine.AI;

namespace Script.Game.Scene.RTS.Navmesh
{
    //  用于客户端预估行军时长，目前没有使用，待删除

    public class RTSNavMeshManager
    {
        private string path = "Assets/ResourcesAssets/OuterCity/Map/Normal/NavMeshSource.obj";
        private string prefabPath = "OuterCity/Map/Normal/NavMeshSourcePrefab";
        private Transform m_Tracked;
        private NavMeshAgent m_Agent;
        private Vector3 m_Size = new Vector3(7200f, 20.0f, 7200f);
        private NavMeshData m_NavMesh;
        private NavMeshDataInstance m_Instance;
        private List<NavMeshBuildSource> m_Sources = new List<NavMeshBuildSource>();
        private NavMeshPath roadPath;
        private GameObject meshObject;
        private bool Inited = false;
        public void Init(Transform parent)
        {
            var tracked = new GameObject {name = "agent"};
            tracked.transform.parent = parent;
            tracked.transform.position = new Vector3(1103,0,1088);// DEBUG 临时设置Agent位置，地图必须全部连通可导航，否则寻路会发生错误
            //tracked.AddComponent<ClickToMove>();
            m_Agent = tracked.AddComponent<NavMeshAgent>();
            m_Tracked = tracked.transform;
            m_NavMesh = new NavMeshData();
            m_Instance = NavMesh.AddNavMeshData(m_NavMesh);
            roadPath = new NavMeshPath();

            // 加载NavMesh
            // ResourceFunc.LoadPrefabAsync(RTSScene.Instance.ResHandlerObj,prefabPath, (o) =>
            // {
            //     if (o == null)
            //     {
            //         return;
            //     }
            //
            //     meshObject = o;
            //     meshObject.transform.position = new Vector3(0,0,0);
            //     NavMeshSourceTag.m_Meshes.Clear();
            //     NavMeshSourceTag.m_Meshes.Add(meshObject.GetComponent<MeshFilter>());
            //     NavMeshSourceTag.Collect(ref m_Sources);
            //     var defaultBuildSettings = NavMesh.GetSettingsByID(0);
            //     defaultBuildSettings.agentRadius = 2.4f;
            //     defaultBuildSettings.agentHeight = 2;
            //     defaultBuildSettings.agentSlope = 30;
            //     defaultBuildSettings.voxelSize = 0.8f;
            //     defaultBuildSettings.minRegionArea = 8f;
            //     var bounds = QuantizedBounds();
            //
            //     updateMeshData(defaultBuildSettings, bounds);
            //
            // });
        }

        private IEnumerator updateMeshData(NavMeshBuildSettings defaultBuildSettings,Bounds bounds)
        {
            Stopwatch stopwatch = Stopwatch.StartNew();
            stopwatch.Reset();
            stopwatch.Start();
            var asyncOperation = NavMeshBuilder.UpdateNavMeshDataAsync(m_NavMesh, defaultBuildSettings, m_Sources, bounds);
            yield return asyncOperation;
            stopwatch.Stop();
            Debug.LogFormat("NavMeshBuilder.updateNavMeshData cost time {0} ms",stopwatch.ElapsedMilliseconds);
            Inited = true;
        }
        public bool CheckIsPositionAvailable(Vector3 position,float radius = 1)
        {

            //return true;
            if (!Inited) return false;
            Vector3 startPosition = new Vector3(1617.6f,0, 2378.0f);
            if (meshObject == null)
            {
                return false;
            }
            else
            {
                m_Agent.Warp(startPosition);
                m_Agent.CalculatePath(position,roadPath);
                if (roadPath.status == NavMeshPathStatus.PathComplete)
                {
                    NavMeshHit hit;
                    if (m_Agent.FindClosestEdge(out hit))
                    {
                        if (hit.distance >= radius)
                        {
                            return true;
                        }
                    }
                }
            }
            return false;
        }

        public List<Vector3> GetPathByStartAndEnd(Vector3 start,Vector3 end)
        {
            if (!Inited) return new List<Vector3>();
            List<Vector3> pathList = new List<Vector3>();
            if (meshObject == null)
            {
                pathList.Add(start);
                pathList.Add(end);
            }
            else
            {
                m_Agent.Warp(start);
                if (m_Agent.CalculatePath(end, roadPath))
                {
                    for (int i = 0; i <  roadPath.corners.Length; i++)
                    {
                        pathList.Add(roadPath.corners[i]);
                    }
                }
                else
                {
                    //如果第一轮失败了，那就先移动到目的地，找到目的地最近的多边形，再寻一次
                    m_Agent.Warp(end);
                    NavMeshHit hit;
                    if (m_Agent.FindClosestEdge(out hit))
                    {
                        m_Agent.Warp(start);
                        if (m_Agent.CalculatePath(hit.position, roadPath))
                        {
                            for (int i = 0; i <  roadPath.corners.Length; i++)
                            {
                                pathList.Add(roadPath.corners[i]);
                            }
                        }
                        else
                        {
                            Debug.LogError("hit fail");
                        }
                    }
                    else
                    {
                        pathList.Add(start);
                    }
                }
            }
            return pathList;
        }

        static Vector3 Quantize(Vector3 v, Vector3 quant)
        {
            float x = quant.x * Mathf.Floor(v.x / quant.x);
            float y = quant.y * Mathf.Floor(v.y / quant.y);
            float z = quant.z * Mathf.Floor(v.z / quant.z);
            return new Vector3(x, y, z);
        }

        Bounds QuantizedBounds()
        {
            // Quantize the bounds to update only when theres a 10% change in size
            var center = Vector3.zero;
            return new Bounds(Quantize(center, 0.1f * m_Size), m_Size);
        }

        public void Dispose()
        {
            m_Instance.Remove();
            m_Sources.Clear();
            NavMeshSourceTag.m_Meshes.Clear();
            if (meshObject != null)
            {
                GameObject.Destroy(meshObject);
            }

            if (m_Tracked != null)
            {
                GameObject.Destroy(m_Tracked.gameObject);
            }
            meshObject = null;
            m_Tracked = null;
        }
    }
}
